/* 
 * Cashbox is the legal property of its developers, whose names are listed in the copyright file included
 * with this source distribution.
 * 
 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
 * General Public License as published by the Free Software Foundation; either version 2 of the License,
 * or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
 * Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with this program; if not,
 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#import <Cashbox/CBObject.h>
#import <Cashbox/CBControllerProtocol.h>
#import <CrashReporter/CrashReporter.h>

#import "CBCashbox.h"
#import "CBAccountController.h"
#import "CBReportController.h"
#import "CBInterfaceController.h"
#import "CBPluginController.h"
#import "CBDataController.h"
#import "CBUndoController.h"
#import "CBMenuController.h"
#import "CBPreferenceWindowController.h"

#import "CBIntFloatTransformer.h"
#import "CBActiveTextColorTransformer.h"
#import "CBUpdateController.h"

@interface CBCashbox (Private)

- (void)setupControllers;
- (void)tearDownControllers;

@end

@implementation CBCashbox

+ (void)initialize {
#ifndef UNIT_TEST
	// register application defaults
	[CBPreferenceWindowController registerDefaults];
	
	// register value transformers
	[NSValueTransformer setValueTransformer:[[[CBIntFloatTransformer alloc] init] autorelease]
									forName:@"CBIntFloatTransformer"];
	[NSValueTransformer setValueTransformer:[[[CBActiveTextColorTransformer alloc] init] autorelease]
									forName:@"CBActiveTextColorTransformer"];
#endif
	
	// register default date behavior
	[NSDateFormatter setDefaultFormatterBehavior:NSDateFormatterBehavior10_4];
	[NSNumberFormatter setDefaultFormatterBehavior:NSNumberFormatterBehavior10_4];
}

- (id)init {
	if ((self = [super init])) {
		[CBObject _setSharedCashboxInstance:self];
	}
	return self;
}


- (NSString *)cashboxApplicationSupportFolder {
	NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
	NSString *appSupportDirectory = nil;
	if ([paths count] == 1) {
		NSFileManager *fileManager = [NSFileManager defaultManager];
		BOOL isDirectory = NO;

		appSupportDirectory = [[[paths objectAtIndex:0] stringByAppendingPathComponent:@"Application Support"]
							   stringByAppendingPathComponent:@"Cashbox"];
		if (![fileManager fileExistsAtPath:appSupportDirectory isDirectory:&isDirectory]) {
			if (![fileManager createDirectoryAtPath:appSupportDirectory attributes:nil]) { return nil; }
		} else {
			if (!isDirectory) {
				return nil;
			}
		}
		return appSupportDirectory;
	}
	return nil;
}

- (NSObject <CBMenuController> *)menuController {
	return menuController;
}

- (NSObject <CBInterfaceController> *)interfaceController {
	return interfaceController;
}

- (NSObject <CBDataController> *)dataController {
	return dataController;
}

- (NSObject <CBUndoController> *)undoController {
	return undoController;
}

- (NSObject <CBUpdateController> *)updateController {
	return updateController;
}

- (NSObject <CBPluginController> *)pluginController {
	return pluginController;
}

- (NSObject <CBAccountController> *)accountController {
	return accountController;
}

- (NSObject <CBReportController> *)reportController {
	return reportController;
}

- (void)setupControllers {
	if (!controllersSetup) {
		accountController = [[CBAccountController alloc] init];
		reportController = [[CBReportController alloc] init];
		pluginController = [[CBPluginController alloc] init];
		dataController = [[CBDataController alloc] init];
#ifndef UNIT_TEST
		undoController = [[CBUndoController alloc] init];
		updateController = [[CBUpdateController alloc] init];
#endif
		
		[updateController controllerDidLoad]; // register for updates first
		[accountController controllerDidLoad]; // account controller needs to be loaded for plugins
		[reportController controllerDidLoad];
		[pluginController controllerDidLoad]; // load before data so all models are loaded
		[dataController controllerDidLoad]; // load the data setup as soon as possible
		[undoController controllerDidLoad];
		[menuController controllerDidLoad];	
		[interfaceController controllerDidLoad]; // make sure data is loaded first

		controllersSetup = TRUE;
	}
}

- (void)tearDownControllers {
	if (!controllersTornDown) {
		[interfaceController controllerWillClose];
		[menuController controllerWillClose];
		[undoController controllerWillClose];
		[dataController controllerWillClose];
		[pluginController controllerWillClose];
		[reportController controllerWillClose];
		[accountController controllerWillClose];
		[updateController controllerWillClose];		

		controllersTornDown = TRUE;
	}
}

#pragma mark application delegate
// ----------------------------------------------------------------------------------------------------
// application delegate
// ----------------------------------------------------------------------------------------------------

- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename {
	[self setupControllers]; // controllers need to be set up before importing
#ifndef UNIT_TEST
	[[self dataController] importFile:filename];
#endif
	return YES;
}

- (void)applicationWillFinishLaunching:(NSNotification *)notification {
#ifdef RELEASE
#ifndef UNIT_TEST
#warning CrashReporter enabled
	[AICrashController enableCrashCatching];
	[AIExceptionController enableExceptionCatching];
#endif
#endif
}

- (void)applicationDidFinishLaunching:(NSNotification *)notification {
	[self setupControllers];
}

- (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag {
	if (!flag) { [(CBInterfaceController *)interfaceController showMainWindow:nil]; }
	return YES;
}

- (void)applicationWillTerminate:(NSNotification *)sender {
	[self tearDownControllers];
}


#pragma mark interface methods
// ----------------------------------------------------------------------------------------------------
// interface methods
// ----------------------------------------------------------------------------------------------------

- (IBAction)showAboutBox:(id)sender {
#ifndef UNIT_TEST
	[[FSAboutBoxController aboutBoxController] setHomepage:@"http://www.fadingred.org/cashbox/"];
	[[FSAboutBoxController aboutBoxController] setBuildInfoDisplayKeys:
	 [NSArray arrayWithObjects:@"build_date", @"build_revision", nil]];
	[[FSAboutBoxController aboutBoxController] showWindow:nil];
#endif
}

- (IBAction)checkForUpdates:(id)sender {
	[(CBUpdateController *)updateController checkForUpdates:sender];
}

@end